using System;
using DslCrossModelFramework.Environment;
using DslCrossModelFramework.NameResolution;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Shell;

namespace DslCrossModelFramework {

    /// <summary>
    /// Provides access to model elements across Dsl surfaces
    /// </summary>
    public class CrossModelManager {

        /// <summary>
        /// Initializes a new instance of the <see cref="CrossModelManager"/> class.
        /// </summary>
        public CrossModelManager() {
                // There is no store reference so we can try to get a global service if we are in visual studio
                IDslIntegrationService service = Package.GetGlobalService(typeof(SDslIntegrationService)) as IDslIntegrationService;
                if (service != null) {
                    service.RegisterDefaultEnvironments();
                }
                if (!EnvironmentConfiguration.Current.IsInitialized) {
                    EnvironmentConfiguration.Current.InitializeEnvironment();
                }
                EnvironmentConfiguration.Current.CheckForDynamicStores();
            
        }

        public CrossModelManager(Store store) : this() {
            IDslIntegrationService service = store.GetService(typeof (SDslIntegrationService)) as IDslIntegrationService;
            if(service != null) {
                service.RegisterDefaultEnvironments();
            }
            if(!EnvironmentConfiguration.Current.IsInitialized) {
                EnvironmentConfiguration.Current.InitializeEnvironment();
            }
            EnvironmentConfiguration.Current.CheckForDynamicStores();
        }


        /// <summary>
        /// Resolves the model element reference.
        /// </summary>
        /// <param name="modelReference">The model reference.</param>
        /// <returns></returns>
        public ModelElement ResolveModelElementReference(string modelReference, IModelFile modelFile) {
            return GetModelDirectory().ResolveModelElementReference(modelReference, modelFile);
        }

        /// <summary>
        /// Gets the model element reference string.
        /// </summary>
        /// <param name="modelElement">The model element.</param>
        /// <returns></returns>
        public string GetModelElementReference(ModelElement modelElement) {
            return GetModelDirectory().GetModelElementReference(modelElement);
        }

        /// <summary>
        /// Gets the model directory.
        /// </summary>
        /// <returns></returns>
        public IModelDirectory GetModelDirectory() {
            return EnvironmentConfiguration.Current.GetModelDirectory();
        }


        /// <summary>
        /// Gets the model directory.
        /// </summary>
        /// <typeparam name="TModelElementType">The type of the model element to filter by.</typeparam>
        /// <returns></returns>
        public IModelDirectory GetModelDirectory<TModelElementType>() {
            //TODO: Implement Model Directory retrieval
            throw new NotImplementedException("Method not Implemented");
        }

        public string GetModelElementName(ModelElement modelElement) {
            return GetModelElementName(modelElement, string.Empty);
        }

        public string GetModelElementName(ModelElement modelElement, string scope) {
            return NameResolutionManager.Current.GetElementName(modelElement);
        }
    }

    public class IntegrationServiceNotAvailableException : Exception {
        public IntegrationServiceNotAvailableException() : base(Resources.Errors.MissingDslIntegrationService) {}
    }
}